﻿using System.Threading.Tasks;

namespace CancellationToken
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            // 1、CancellationTokenSource可以理解为CancellationToken的控制器
            // 2、控制它什么时候变成取消状态的一个对象，它有一个CancellationToken类型的属性Token
            // 3、只要CancellationTokenSource创建，这个Token也会被创建，同时Token会和这个CancellationTokenSource绑定
            // 4、当我们创建异步操作时，可以传入一个CancellationToken，当异步操作处于等待执行状态时，可以通过设置CancellationToken为取消状态将异步操作取消执行
            using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(60)))
            {
                // 获取 CancellationToken
                var token = cts.Token;

                // 启动一个异步任务
                Task myTask = Task.Run(() => DoWork(token));

                // 模拟等待一段时间
                await Task.Delay(2000);

                // 取消任务
                cts.Cancel();

                try
                {
                    await myTask; // 不会引发异常，但会检查取消标记
                    token.ThrowIfCancellationRequested(); // 这里会抛出异常，你可以选择是否捕获
                    Console.WriteLine(myTask.Status);
                }
                catch (Exception ex)
                {
                    if (ex is OperationCanceledException || ex is TaskCanceledException)
                    {
                        Console.WriteLine("任务被取消");
                    }
                    else
                    {
                        Console.WriteLine("其他异常：" + ex.Message);
                    }
                }
            }

        }

        /// <summary>
        /// 一些操作
        /// </summary>
        /// <param name="token"></param>
        static void DoWork(System.Threading.CancellationToken token)
        {
            try
            {
                while (!token.IsCancellationRequested)
                {
                    // 模拟任务执行
                    Console.WriteLine("正在执行任务...");
                    Thread.Sleep(500);
                }

                // 在取消请求发生时抛出 OperationCanceledException
                token.ThrowIfCancellationRequested();
                
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("任务取消请求已接收");
            }
        }
    }
}